package cn.adelyn.base.auth.service;

import cn.adelyn.base.api.auth.constant.AuthAccountStatusEnum;
import cn.adelyn.base.api.auth.pojo.bo.UserInfoInTokenBO;
import cn.adelyn.base.api.snowfalke.feign.SnowflakeFeignClient;
import cn.adelyn.base.auth.dao.AuthAccountDaoService;
import cn.adelyn.base.auth.pojo.bo.AuthAccountBO;
import cn.adelyn.base.auth.pojo.dto.RegisterAccountDTO;
import cn.adelyn.base.auth.pojo.model.AuthAccountModel;
import cn.adelyn.common.core.cglib.CglibUtil;
import cn.adelyn.common.core.execption.AdelynException;
import cn.adelyn.common.core.response.ResponseEnum;
import cn.adelyn.common.core.response.ServerResponseEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Objects;

/**
 * @author chengze
 * @date 2022/12/20
 * @desc 账号认证
 */
@Service
public class AuthAccountService {

	@Autowired
	private SnowflakeFeignClient snowflakeFeignClient;

	@Autowired
	private AuthAccountDaoService authAccountDaoService;

	@Autowired
	private PasswordEncoder passwordEncoder;

	public static final String USER_NOT_FOUND_SECRET = "$2a$10$qgsD1Ez6oBYiE61dLAAkBO9dKzrv5oho3J9G0nR/eIDs75oY4hCvq";

	public UserInfoInTokenBO getUserInfoInTokenByInputUserNameAndPassword(String userName, String password) {

		AuthAccountBO authAccountInVerifyBO = authAccountDaoService
				.getAuthAccountBOByUserName(userName);

		if (authAccountInVerifyBO == null) {
			// 防止计时攻击（Timingattack）
			// 通过设备运算的用时来推断出所使用的运算操作，或者通过对比运算的时间推定数据位于哪个存储设备，或者利用通信的时间差进行数据窃取。
			mitigateAgainstTimingAttack(password);
			throw new AdelynException(ResponseEnum.ACCOUNT_VERIFY_FAIL);
		}

		if (Objects.equals(authAccountInVerifyBO.getStatus(), AuthAccountStatusEnum.DISABLE.value())) {
			throw new AdelynException(ResponseEnum.ACCOUNT_DISABLED);
		}

		if (!passwordEncoder.matches(password, authAccountInVerifyBO.getPassword())) {
			throw new AdelynException(ResponseEnum.ACCOUNT_VERIFY_FAIL);
		}

		return CglibUtil.copy(authAccountInVerifyBO, UserInfoInTokenBO.class);
	}

	public ServerResponseEntity registerAccount(RegisterAccountDTO registerAccountDTO){

		registerAccountDTO.setPassword(passwordEncoder.encode(registerAccountDTO.getPassword()));

		AuthAccountModel authAccountModel = CglibUtil.copy(registerAccountDTO, AuthAccountModel.class);
		authAccountModel.setUserId(snowflakeFeignClient.snowflakeId().getData());

		authAccountDaoService.registerAccount(authAccountModel);

		return ServerResponseEntity.success();
	}

	/**
	 * 防止计时攻击
	 */
	private void mitigateAgainstTimingAttack(String presentedPassword) {
		this.passwordEncoder.matches(presentedPassword, USER_NOT_FOUND_SECRET);
	}

}
